#include	"Vector4d.h"
#include	"Vector4f.h"
#include	"Vector4i.h"
#include	<cmath>

const double Vector4d::EPSILON = 0.00001;

Vector4d::Vector4d()
{
}

Vector4d::Vector4d(double x, double y, double z, double w)
{
	Set(x, y, z, w);
}

Vector4d::Vector4d(float x, float y, float z, float w)
{
	Set(x, y, z, w);
}

Vector4d::Vector4d(int x, int y, int z, int w)
{
	Set(x, y, z, w);
}

Vector4d::Vector4d(const Vector4d & vec)
{
	Set(vec);
}

Vector4d::Vector4d(const Vector4f & vec)
{
	Set(vec);
}

Vector4d::Vector4d(const Vector4i & vec)
{
	Set(vec);
}

Vector4d::Vector4d(const double * arr)
{
	Set(arr);
}

Vector4d::Vector4d(const float * arr)
{
	Set(arr);
}

Vector4d::Vector4d(const int * arr)
{
	Set(arr);
}

Vector4d::~Vector4d()
{
}

void Vector4d::Set(double x, double y, double z, double w)
{
	m_data[0] = x;
	m_data[1] = y;
	m_data[2] = z;
	m_data[3] = w;
}

void Vector4d::Set(float x, float y, float z, float w)
{
	m_data[0] = double(x);
	m_data[1] = double(y);
	m_data[2] = double(z);
	m_data[3] = double(w);
}

void Vector4d::Set(int x, int y, int z, int w)
{
	m_data[0] = double(x);
	m_data[1] = double(y);
	m_data[2] = double(z);
	m_data[3] = double(w);
}

void Vector4d::Set(const double * arr)
{
	m_data[0] = arr[0];
	m_data[1] = arr[1];
	m_data[2] = arr[2];
	m_data[3] = arr[3];
}

void Vector4d::Set(const float * arr)
{
	m_data[0] = double(arr[0]);
	m_data[1] = double(arr[1]);
	m_data[2] = double(arr[2]);
	m_data[3] = double(arr[3]);
}

void Vector4d::Set(const int * arr)
{
	m_data[0] = double(arr[0]);
	m_data[1] = double(arr[1]);
	m_data[2] = double(arr[2]);
	m_data[3] = double(arr[3]);
}

Vector4d::operator const double*() const
{
	return m_data;
}

Vector4d::operator double*()
{
	return m_data;
}

const Vector4d & Vector4d::operator+() const
{
	return *this;
}

Vector4d & Vector4d::operator+()
{
	return *this;
}

Vector4d Vector4d::operator-() const
{
	return Vector4d(-m_data[0], -m_data[1], -m_data[2], -m_data[3]);
}

Vector4d & Vector4d::operator=(const Vector4d & vec)
{
	Set(vec);
	return *this;
}

Vector4d & Vector4d::operator=(const Vector4f & vec)
{
	Set(vec);
	return *this;
}

Vector4d & Vector4d::operator=(const Vector4i & vec)
{
	Set(vec);
	return *this;
}

Vector4d & Vector4d::operator+=(const Vector4d & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
	return *this;
}

Vector4d & Vector4d::operator+=(const Vector4f & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
	return *this;
}

Vector4d & Vector4d::operator+=(const Vector4i & vec)
{
	Set(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
	return *this;
}

Vector4d & Vector4d::operator-=(const Vector4d & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
	return *this;
}

Vector4d & Vector4d::operator-=(const Vector4f & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
	return *this;
}

Vector4d & Vector4d::operator-=(const Vector4i & vec)
{
	Set(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
	return *this;
}

Vector4d & Vector4d::operator*=(double num)
{
	Set(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
	return *this;
}

Vector4d & Vector4d::operator*=(float num)
{
	Set(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
	return *this;
}

Vector4d & Vector4d::operator*=(int num)
{
	Set(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
	return *this;
}

Vector4d & Vector4d::operator/=(double num)
{
	Set(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
	return *this;
}

Vector4d & Vector4d::operator/=(float num)
{
	Set(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
	return *this;
}

Vector4d & Vector4d::operator/=(int num)
{
	Set(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
	return *this;
}

Vector4d Vector4d::operator+(const Vector4d & vec) const
{
	return Vector4d(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
}

Vector4d Vector4d::operator+(const Vector4f & vec) const
{
	return Vector4d(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
}

Vector4d Vector4d::operator+(const Vector4i & vec) const
{
	return Vector4d(m_data[0] + vec[0], m_data[1] + vec[1], m_data[2] + vec[2], m_data[3] + vec[3]);
}

Vector4d Vector4d::operator-(const Vector4d & vec) const
{
	return Vector4d(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
}

Vector4d Vector4d::operator-(const Vector4f & vec) const
{
	return Vector4d(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
}

Vector4d Vector4d::operator-(const Vector4i & vec) const
{
	return Vector4d(m_data[0] - vec[0], m_data[1] - vec[1], m_data[2] - vec[2], m_data[3] - vec[3]);
}

Vector4d Vector4d::operator*(double num) const
{
	return Vector4d(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
}

Vector4d Vector4d::operator*(float num) const
{
	return Vector4d(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
}

Vector4d Vector4d::operator*(int num) const
{
	return Vector4d(m_data[0] * num, m_data[1] * num, m_data[2] * num, m_data[3] * num);
}

Vector4d Vector4d::operator/(double num) const
{
	return Vector4d(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
}

Vector4d Vector4d::operator/(float num) const
{
	return Vector4d(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
}

Vector4d Vector4d::operator/(int num) const
{
	return Vector4d(m_data[0] / num, m_data[1] / num, m_data[2] / num, m_data[3] / num);
}

Vector4d operator*(double num, const Vector4d & vec)
{
	return Vector4d(vec[0] * num, vec[1] * num, vec[2] * num, vec[3] * num);
}

Vector4d operator*(float num, const Vector4d & vec)
{
	return Vector4d(vec[0] * num, vec[1] * num, vec[2] * num, vec[3] * num);
}

Vector4d operator*(int num, const Vector4d & vec)
{
	return Vector4d(vec[0] * num, vec[1] * num, vec[2] * num, vec[3] * num);
}

bool Vector4d::operator==(const Vector4d & vec) const
{
	return ((vec[0] - Vector4d::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector4d::EPSILON))
		&& ((vec[1] - Vector4d::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector4d::EPSILON))
		&& ((vec[2] - Vector4d::EPSILON) <= m_data[2]) && (m_data[2] <= (vec[2] + Vector4d::EPSILON))
		&& ((vec[3] - Vector4d::EPSILON) <= m_data[3]) && (m_data[3] <= (vec[3] + Vector4d::EPSILON));
}

bool Vector4d::operator==(const Vector4f & vec) const
{
	return ((vec[0] - Vector4d::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector4d::EPSILON))
		&& ((vec[1] - Vector4d::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector4d::EPSILON))
		&& ((vec[2] - Vector4d::EPSILON) <= m_data[2]) && (m_data[2] <= (vec[2] + Vector4d::EPSILON))
		&& ((vec[3] - Vector4d::EPSILON) <= m_data[3]) && (m_data[3] <= (vec[3] + Vector4d::EPSILON));
}

bool Vector4d::operator==(const Vector4i & vec) const
{
	return ((vec[0] - Vector4d::EPSILON) <= m_data[0]) && (m_data[0] <= (vec[0] + Vector4d::EPSILON))
		&& ((vec[1] - Vector4d::EPSILON) <= m_data[1]) && (m_data[1] <= (vec[1] + Vector4d::EPSILON))
		&& ((vec[2] - Vector4d::EPSILON) <= m_data[2]) && (m_data[2] <= (vec[2] + Vector4d::EPSILON))
		&& ((vec[3] - Vector4d::EPSILON) <= m_data[3]) && (m_data[3] <= (vec[3] + Vector4d::EPSILON));
}

bool operator==(const Vector4i & veci, const Vector4d & vecd)
{
	return ((veci[0] - Vector4d::EPSILON) <= vecd[0]) && (vecd[0] <= (veci[0] + Vector4d::EPSILON))
		&& ((veci[1] - Vector4d::EPSILON) <= vecd[1]) && (vecd[1] <= (veci[1] + Vector4d::EPSILON))
		&& ((veci[2] - Vector4d::EPSILON) <= vecd[2]) && (vecd[2] <= (veci[2] + Vector4d::EPSILON))
		&& ((veci[3] - Vector4d::EPSILON) <= vecd[3]) && (vecd[3] <= (veci[3] + Vector4d::EPSILON));
}

bool operator==(const Vector4f & vecf, const Vector4d & vecd)
{
	return ((vecf[0] - Vector4d::EPSILON) <= vecd[0]) && (vecd[0] <= (vecf[0] + Vector4d::EPSILON))
		&& ((vecf[1] - Vector4d::EPSILON) <= vecd[1]) && (vecd[1] <= (vecf[1] + Vector4d::EPSILON))
		&& ((vecf[2] - Vector4d::EPSILON) <= vecd[2]) && (vecd[2] <= (vecf[2] + Vector4d::EPSILON))
		&& ((vecf[3] - Vector4d::EPSILON) <= vecd[3]) && (vecd[3] <= (vecf[3] + Vector4d::EPSILON));
}

bool Vector4d::operator!=(const Vector4d & vec) const
{
	return ((vec[0] - Vector4d::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector4d::EPSILON))
		|| ((vec[1] - Vector4d::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector4d::EPSILON))
		|| ((vec[2] - Vector4d::EPSILON) > m_data[2]) || (m_data[2] > (vec[2] + Vector4d::EPSILON))
		|| ((vec[3] - Vector4d::EPSILON) > m_data[3]) || (m_data[3] > (vec[3] + Vector4d::EPSILON));
}

bool Vector4d::operator!=(const Vector4f & vec) const
{
	return ((vec[0] - Vector4d::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector4d::EPSILON))
		|| ((vec[1] - Vector4d::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector4d::EPSILON))
		|| ((vec[2] - Vector4d::EPSILON) > m_data[2]) || (m_data[2] > (vec[2] + Vector4d::EPSILON))
		|| ((vec[3] - Vector4d::EPSILON) > m_data[3]) || (m_data[3] > (vec[3] + Vector4d::EPSILON));
}

bool Vector4d::operator!=(const Vector4i & vec) const
{
	return ((vec[0] - Vector4d::EPSILON) > m_data[0]) || (m_data[0] > (vec[0] + Vector4d::EPSILON))
		|| ((vec[1] - Vector4d::EPSILON) > m_data[1]) || (m_data[1] > (vec[1] + Vector4d::EPSILON))
		|| ((vec[2] - Vector4d::EPSILON) > m_data[2]) || (m_data[2] > (vec[2] + Vector4d::EPSILON))
		|| ((vec[3] - Vector4d::EPSILON) > m_data[3]) || (m_data[3] > (vec[3] + Vector4d::EPSILON));
}

bool operator!=(const Vector4i & veci, const Vector4d & vecd)
{
	return ((veci[0] - Vector4d::EPSILON) > vecd[0]) || (vecd[0] > (veci[0] + Vector4d::EPSILON))
		|| ((veci[1] - Vector4d::EPSILON) > vecd[1]) || (vecd[1] > (veci[1] + Vector4d::EPSILON))
		|| ((veci[2] - Vector4d::EPSILON) > vecd[2]) || (vecd[2] > (veci[2] + Vector4d::EPSILON))
		|| ((veci[3] - Vector4d::EPSILON) > vecd[3]) || (vecd[3] > (veci[3] + Vector4d::EPSILON));
}

bool operator!=(const Vector4f & vecf, const Vector4d & vecd)
{
	return ((vecf[0] - Vector4d::EPSILON) > vecd[0]) || (vecd[0] > (vecf[0] + Vector4d::EPSILON))
		|| ((vecf[1] - Vector4d::EPSILON) > vecd[1]) || (vecd[1] > (vecf[1] + Vector4d::EPSILON))
		|| ((vecf[2] - Vector4d::EPSILON) > vecd[2]) || (vecd[2] > (vecf[2] + Vector4d::EPSILON))
		|| ((vecf[3] - Vector4d::EPSILON) > vecd[3]) || (vecd[3] > (vecf[3] + Vector4d::EPSILON));
}
double Vector4d::LengthSquare() const
{
	return double(m_data[0] * m_data[0]) + double(m_data[1] * m_data[1]) + double(m_data[2] * m_data[2]) + double(m_data[3] * m_data[3]);
}

double Vector4d::Length() const
{
	return std::sqrt(double(m_data[0] * m_data[0]) + double(m_data[1] * m_data[1]) + double(m_data[2] * m_data[2]) + double(m_data[3] * m_data[3]));
}

void Vector4d::Normalize()
{
	double inverse_length = 1 / Length();
	Set(double(m_data[0] * inverse_length), double(m_data[1] * inverse_length), double(m_data[2] * inverse_length), double(m_data[3] * inverse_length));
}

Vector4d Vector4d::Normal() const
{
	double inverse_length = 1 / Length();
	return Vector4d(double(m_data[0] * inverse_length), double(m_data[1] * inverse_length), double(m_data[2] * inverse_length), double(m_data[3] * inverse_length));
}

